I was finishing up work on a hashing library and started testing my hash values against other sources to ensure I was doing everything right. Unfortunately, my hashes were off. Long story short, I was converting the hashed byte array into a string using a Base64 string encoder, but what you are supposed to do is convert it into a Hexadecimal string – that is if you want to conform to standards. I searched around and found out how you are supposed do this from post called How do you convert Byte Array to Hexadecimal String, and vice versa, in C#? on Stack Overflow, as well as a post from MSDN entitled byte[] Array to Hex String. In the first post, two options are presented, but no information about which way is faster or why to do one way over the other. So I decided to find out myself because if I have the option, I’d prefer my code to be faster.
Option 1: Building the hex string using a for loop 
In my meanders looking for a solution to the MD5 hash, this is the algorithm that I ran into the most. The method simply runs through each byte in the byte array and outputs the text based version using standard string formatting with a StringBuilder.
public static string CreateHexString(byte[] data)     
{      
  StringBuilder hex = new StringBuilder(data.Length * 2);      
  foreach (byte b in data)      
  {      
    hex.AppendFormat("{0:x2}", b);      
  }      
  return hex.ToString();      
}
Option 2: Using the bit converter and replacing the delimiters 
The second option uses the BitConverter class to create a string – but the string that gets created is delimited by a series of dashes that must subsequently be removed. This is some very succinct code.
| 
					 1  | 
						public static string CreateHexString(byte[] data){  return BitConverter.ToString(data).Replace("-","");}  | 
					
Option 3: Dark Magic 
This piece of code from PZahra from the MSDN link uses right shifting and dark magic that culminates in a hexadecimal string. I modified it slightly from the original code so it would match the strings produced by the other hexadecimal methods.
public static string CreateHexString(byte[] data) 
{ 
 char[] c = new char[data.Length * 2]; 
 byte b; 
 for (int y = 0, x = 0; y < data.Length; ++y, ++x) 
 { 
 b = ((byte)(data[y] >> 4)); 
 c[x] = (char)(b > 9 ? b + 0x37 : b + 0x30); 
 b = ((byte)(data[y] & 0xF)); 
 c[++x] = (char)(b > 9 ? b + 0x37 : b + 0x30); 
 } 
}
Using my performance timer from a previous post (though it’s been slightly modified since then) I ran both options through a series of tests and determined the following:
Option 1 runs approximately 40,000 ops/sec 
Option 2 runs approximately 282,000 ops/sec 
Option 3 runs approximately 304,000 ops/sec
So, using the for-loop is the slowest possible way of doing things, which I find interesting because it seems to be widely used for this purpose. Opting for the BitConverter is more than 7 times faster than the for loop (at least on my system) and it only takes a single line of code to write. Perhaps the BitConverter is a bit obscure (pun definitely intended) so nobody uses it. And if you don’t mind losing a lot of readability, then you can eek out even more performance using PZahra’s code.
        
Load comments